//*****************************************************************************
//
// LED_Cube.c - 8x8x8 Animation LED Cube Applicaiton
//
// Developed by:
//    David Racine
//    Michael Risley
//
//*****************************************************************************
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h" 
#include "driverlib/pin_map.h" 
#include "utils/uartstdio.h"
#include "driverlib/gpio.h"
#include "inc/hw_ssi.h"
#include "driverlib/ssi.h"
#include "inc/hw_ints.h"
#include "inc/hw_timer.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"

#include "Functions/cube_functions.h"
#include "Functions/binary.h"
#include "Animations/animations.h"
#include "Animations/shapes.h"

#include "Animations/effect.h"
#include "Animations/launch_effect.h"
#include "Animations/draw.h"




int cubeShow = 0,new = 0;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif

void cube_show_loop(unsigned long cycles);

//*****************************************************************************
//
// Timer ISR used to update image
//
//*****************************************************************************
void
Timer1AIntHandler(void)
{
	TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
	TimerLoadSet(TIMER1_BASE, TIMER_A, ROM_SysCtlClockGet() / g_ulImageTime);
	g_updateFlag = 1;
}

//*****************************************************************************
//
// Timer ISR used to refresh layers
//
//*****************************************************************************
void
Timer0AIntHandler(void)
{

    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);


    SetLayerState(g_ulLayerIndex,0);

    WriteLayer();

    // Find next layer.
    g_ulLayerIndex++;

    // Roll-over if necessary.
    if( g_ulLayerIndex == NUM_LAYERS){
    	g_ulLayerIndex = 0;
    }
    
    SysCtlDelay(1200);

    // Turn ON the next layer.
    SetLayerState(g_ulLayerIndex,1);
}



//*****************************************************************************
//
// Initialize peripherals
//
//*****************************************************************************
void setupPeripherals()
{
    // 
    // Setup timer interrupt
    //   (for refreshing layers)
    //   Triggers every X seconds
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE, TIMER_A, ROM_SysCtlClockGet() / REFRESH_RATE);
    IntEnable(INT_TIMER0A);
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    //
    // Setup timer interrupt
    // (for refreshing image)
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER1_BASE, TIMER_A, ROM_SysCtlClockGet() / g_ulImageTime);
    IntEnable(INT_TIMER1A);
    TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
    IntMasterEnable();

    //
    // Enable the SSI3 periph.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    GPIOPinConfigure(GPIO_PK0_SSI3CLK);
    GPIOPinConfigure(GPIO_PK3_SSI3TX);
    GPIOPinTypeSSI(GPIO_PORTK_BASE, GPIO_PIN_3 | GPIO_PIN_0 );
    
    //
    // Configure the SSI port for SPI Master mode.
    //
    SSIConfigSetExpClk(SSI3_BASE, ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
                       SSI_MODE_MASTER, 10000000, 16);
                       
    //
    // Enable SSI.
    //
    SSIEnable(SSI3_BASE);
    
    while(SSIDataGetNonBlocking(SSI3_BASE, g_ulDataRx));
    
    // Setup GPIO to latch data.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
    GPIOPinTypeGPIOOutput(LATCH_PORT, LATCH_PIN);
    GPIOPinWrite(LATCH_PORT , LATCH_PIN, 0);
    
    // Setup the BLANK pin
    GPIOPinTypeGPIOOutput(BLANK_PORT, BLANK_PIN);
    
    // Setup Layer GPIOs
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_0_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_1_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_2_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_3_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_4_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_5_PIN);
    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_6_PIN);


    //PD7 configure out of NMI function
    HWREG(LAYER_PORT + GPIO_O_LOCK ) = 0x4c4f434b;
    HWREG(LAYER_PORT + GPIO_O_CR ) = 0xff;
    HWREG(LAYER_PORT + GPIO_O_LOCK ) = 0x01;




    GPIOPinTypeGPIOOutput(LAYER_PORT, LAYER_7_PIN);
	
}
void
cube_show_loop(unsigned long cycles)
{
    if(cycles<6 && new==1)cycles = 15;
	g_ulImageTime = cycles;
	switch_buff();
	g_updateFlag = 0;
	while(g_ulLayerIndex);
	while(!g_updateFlag);
}

//*****************************************************************************
//
// MAIN
//
//*****************************************************************************
int
main(void)
{

    //
    // Enable lazy stacking for interrupt handlers.
    //
    ROM_FPUEnable();
    ROM_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
                       
    //
    // Setup and enable all used peripherals.
    //
    setupPeripherals();

    InitLayers();

    //
    // Enable timer to refresh layers
    //
    TimerEnable(TIMER0_BASE, TIMER_A);

    //
    // Enable timer to refresh image
    //
    TimerEnable(TIMER1_BASE, TIMER_A);

    //
    // Set BLANK low (enable all LED ICs)
    //
    GPIOPinWrite(BLANK_PORT , BLANK_PIN, 0);

    int i;

    while(1)
    {

    	cube_string_belt("LED Cube");
    	cube_fixed_string();
    	cube_string_to_front("Stellaris Cortex M4F  ");
        cube_outline();
        //diamond();
        cube_sonic();
        cubes_2();
     	cube_stripes();
        cubes_4();
        cube_waves();
        outline_shrink();
        SysCtlDelay(1000);
        cube_explosion();
        cube_stars();


        new=1;
        for (i=0; i<EFFECTS_TOTAL; i++){
        			launch_effect(i);
        }
        new=0;

        cube_explosion();
        sine_3d();
    	cube_belt_wipe();
        cube_walking();
		cube_stripes();
		cube_explosion();
		cube_invaders();



    }

}
